﻿namespace DueDatePickerSample.Controls
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Navigation;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.Controls.Primitives;

    public partial class DueDatePickerPage : PhoneApplicationPage, INotifyPropertyChanged, IDateTimePickerPage
    {
        public enum DueDate
        {
            NoDueDate,
            Today,
            Tomorrow,
            TwoDaysLater,
            ThreeDaysLater,
            FourDaysLater,
            CustomDate
        }

        public DueDatePickerPage()
        {
            InitializeComponent();
            this.DueDateValues = Enum.GetValues(typeof(DueDate)).Cast<DueDate>().ToList();
            this.Loaded += (obj, args) => this.SelectedItem = this.EnumFromDate(this.Value);
        }

        private List<DueDate> dueDateValues;
        public List<DueDate> DueDateValues
        {
            get
            {
                return this.dueDateValues;
            }

            set
            {
                this.dueDateValues = value;
                this.NotifyPropertyChanged();
            }
        }

        private DueDate selectedItem;
        public DueDate SelectedItem
        {
            get
            {
                return this.selectedItem;
            }

            set
            {
                this.selectedItem = value;
                this.NotifyPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var propertyChangedCopy = this.PropertyChanged;
            if (propertyChangedCopy != null)
            {
                propertyChangedCopy(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public void SetFlowDirection(System.Windows.FlowDirection flowDirection)
        {
        }

        public DateTime? Value { get; set; }

        private void OnListItemTapped(object sender, System.Windows.Input.GestureEventArgs e)
        {
            // if user selects "custom date" then open date picker page
            if (this.SelectedItem == DueDate.CustomDate)
            {
                OpenPickerPage();
                return;
            }

            this.Value = this.DateTimeFromEnum(this.SelectedItem);
            NavigationService.GoBack();
        }

        private DateTime DateTimeFromEnum(DueDate enumItem)
        {
            return DateTime.Today.AddDays((int)enumItem - 1);
        }

        private DueDate EnumFromDate(DateTime? dateTime)
        {
            if (dateTime == null)
            {
                return DueDate.NoDueDate;
            }

            foreach (var enumValue in Enum.GetValues(typeof(DueDate)))
            {
                if (dateTime.Value == DateTime.Today.AddDays((int)enumValue - 1))
                {
                    return (DueDate)enumValue;
                }
            }

            if (dateTime.Value > DateTime.Today.AddDays(Enum.GetValues(typeof(DueDate)).Length - 1))
            {
                return DueDate.CustomDate;
            }

            // this goes also here as by default DatePicker gives current date if not set
            // 
            return DueDate.NoDueDate;
        }


        #region DefaultPicker

        private PhoneApplicationFrame _frame;
        private object _frameContentWhenOpened;
        private NavigationInTransition _savedNavigationInTransition;
        private NavigationOutTransition _savedNavigationOutTransition;
        private IDateTimePickerPage _dateTimePickerPage;

        private void OpenPickerPage()
        {
            if (null == _frame)
            {
                // Hook up to necessary events and navigate
                _frame = Application.Current.RootVisual as PhoneApplicationFrame;
                if (null != _frame)
                {
                    _frameContentWhenOpened = _frame.Content;

                    // Save and clear host page transitions for the upcoming "popup" navigation
                    UIElement frameContentWhenOpenedAsUIElement = _frameContentWhenOpened as UIElement;
                    if (null != frameContentWhenOpenedAsUIElement)
                    {
                        _savedNavigationInTransition = TransitionService.GetNavigationInTransition(frameContentWhenOpenedAsUIElement);
                        TransitionService.SetNavigationInTransition(frameContentWhenOpenedAsUIElement, null);
                        _savedNavigationOutTransition = TransitionService.GetNavigationOutTransition(frameContentWhenOpenedAsUIElement);
                        TransitionService.SetNavigationOutTransition(frameContentWhenOpenedAsUIElement, null);
                    }

                    _frame.Navigated += OnFrameNavigated;
                    _frame.NavigationStopped += OnFrameNavigationStoppedOrFailed;
                    _frame.NavigationFailed += OnFrameNavigationStoppedOrFailed;

                    _frame.Navigate(new Uri("/Microsoft.Phone.Controls.Toolkit;component/DateTimePickers/DatePickerPage.xaml", UriKind.Relative));
                }
            }
        }

        private void OnFrameNavigated(object sender, NavigationEventArgs e)
        {
            if (e.Content == _frameContentWhenOpened)
            {
                // Navigation to original page; close the picker page
                ClosePickerPage();
            }
            else if (null == _dateTimePickerPage)
            {
                // Navigation to a new page; capture it and push the value in
                var pickerPage = e.Content as IDateTimePickerPage;

                if (null != pickerPage)
                {
                    _dateTimePickerPage = pickerPage;
                    _dateTimePickerPage.Value = Value.GetValueOrDefault(DateTime.Now);

                    pickerPage.SetFlowDirection(this.FlowDirection);
                }
            }
        }

        private void OnFrameNavigationStoppedOrFailed(object sender, EventArgs e)
        {
            // Abort
            ClosePickerPage();
        }

        private void ClosePickerPage()
        {
            // Unhook from events
            if (null != _frame)
            {
                _frame.Navigated -= OnFrameNavigated;
                _frame.NavigationStopped -= OnFrameNavigationStoppedOrFailed;
                _frame.NavigationFailed -= OnFrameNavigationStoppedOrFailed;

                // Restore host page transitions for the completed "popup" navigation
                UIElement frameContentWhenOpenedAsUIElement = _frameContentWhenOpened as UIElement;
                if (null != frameContentWhenOpenedAsUIElement)
                {
                    TransitionService.SetNavigationInTransition(frameContentWhenOpenedAsUIElement, _savedNavigationInTransition);
                    _savedNavigationInTransition = null;
                    TransitionService.SetNavigationOutTransition(frameContentWhenOpenedAsUIElement, _savedNavigationOutTransition);
                    _savedNavigationOutTransition = null;
                }

                _frame = null;
                _frameContentWhenOpened = null;
            }

            // Commit the value if available
            if (null != _dateTimePickerPage)
            {
                if (_dateTimePickerPage.Value.HasValue)
                {
                    Value = _dateTimePickerPage.Value.Value;

                    //// OUR CODE
                    // if user selects as "custom date" date earlier then today then set today
                    if (this.Value < DateTime.Today)
                    {
                        this.Value = DateTime.Today;
                    }
                    //// OUR CODE
                }
                //// OUR CODE
                else
                {
                    this.Value = null;
                }
                //// OUR CODE

                _dateTimePickerPage = null;
            }

            //// OUR CODE
            NavigationService.GoBack();
            //// OUR CODE
        }

        #endregion
    }
}